package com.zjpavt.client.udp.artnet;

import com.zjpavt.client.hal.ArtNetConfig;
import com.zjpavt.client.udp.artnet.controlPanel.AbstractArtNetController;
import com.zjpavt.client.udp.artnet.controlPanel.MaLightingController;
import com.zjpavt.client.udp.artnet.service.ArtNetLoopServiceImpl;
import com.zjpavt.client.udp.artnet.service.ArtNetService;
import com.zjpavt.client.util.ClientConfig;
import com.zjpavt.client.util.LoggerUtil;
import com.zjpavt.client.util.PropertiesUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;


/**
 * 用于接收art-net信号
 * @author: zyc
 */
public class ArtNetServer {
    private static final Logger log = LoggerFactory.getLogger(ArtNetServer.class);

    private static class InnerClass {
        static final ArtNetServer artNetServer = new ArtNetServer();
    }
    public static ArtNetServer getInstance() {
        return InnerClass.artNetServer;
    }

    /**
     * 控制台类型 决定了用什么方式解析数据
     */
    private AbstractArtNetController artNetController;

    /**
     * 解析出的数据 的业务处理逻辑
     */
    private ArtNetService artNetService;

    /**
     * 构造方法
     */
    private ArtNetServer() {
        try {
            if ("true".equals(PropertiesUtil.getPropertiesDefault("ArtNetServer",""))) {
                new Thread(() -> {
                    ArtNetConfig.update();
                    this.artNetService = new ArtNetLoopServiceImpl();
                    initServer(ClientConfig.OUTPUT_UDP_ART_NET_SERVER_PORT);
                    log.info("art net start success");
                }).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 当不需要控台输入信号的时候 调用该解控停止Udp信号的监听
     */
    private void stopServerWhenWithoutController() {
    }

    /**
     * 初始化服务器 监听指定接口
     * @param port
     */
    private void initServer(int port) {
        final NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(1,new DefaultThreadFactory("ArtNetServer"));
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.channel(NioDatagramChannel.class);
        bootstrap.group(nioEventLoopGroup);
        bootstrap.handler(new ChannelInitializer<NioDatagramChannel>() {
            @Override
            protected void initChannel(NioDatagramChannel ch) throws Exception {
                ch.pipeline().addLast(new ArtNetServerHandler());
            }
        });
        try {
            log.info("begin start ArtNetServer success!");
            ChannelFuture bind = bootstrap.bind(port).sync();
            log.info("start ArtNetServer success!");
            bind.channel().closeFuture().await();
        } catch (Exception e) {
            log.error(LoggerUtil.convertException2String(e));
        }
        finally {
            nioEventLoopGroup.shutdownGracefully();
        }
    }

    private class ArtNetServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
//            if (!"2.0.0.13".equals(msg.sender().getAddress().getHostAddress())) {
//                return;
//            }
            if (artNetController == null || ArtNetConfig.ARTNET_SERVER_OFF.equals(artNetController.getType())) {
                return;
            }
            ByteBuf buf = msg.copy().content();
            byte[] request = new byte[buf.readableBytes()];
            buf.readBytes(request);
//            buf.
            ReferenceCountUtil.release(buf);
            byte[] msg1 = artNetController.getControlData(request);
            if (msg1 == null) {
                return;
            }
            artNetService.execute(msg1);
            System.out.println(msg);
        }

    }

    public void setArtNetController(AbstractArtNetController artNetController) {
        log.info("controller changed" + artNetController);
        this.artNetController = artNetController;
        if (ArtNetConfig.ARTNET_SERVER_OFF.equals(artNetController.getType())) {
//            todo close Udp Server
        }
    }

    public static void main(String[] args) {
        try {
            ArtNetServer artNetServer = new ArtNetServer();
            artNetServer.artNetController = new MaLightingController(4,0,36,1);
            artNetServer.artNetService = new ArtNetLoopServiceImpl();
            artNetServer.initServer(ClientConfig.OUTPUT_UDP_ART_NET_SERVER_PORT);
            Thread.sleep(5000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

